Skip to content

Add preamble section and preserve action to SDKs#1713

Merged
SteveSandersonMS merged 5 commits into
mainfrom
mackinnonbuck/preamble-prompt-section
Jun 24, 2026
Merged

Add preamble section and preserve action to SDKs#1713
SteveSandersonMS merged 5 commits into
mainfrom
mackinnonbuck/preamble-prompt-section

Conversation

@MackinnonBuck

Copy link
Copy Markdown
Collaborator

Why

The runtime recently reworked system prompt customization (copilot-agent-runtime#10025) to fix a bug where identity: { action: "replace" } silently deleted sibling sections (tone, tool efficiency, etc.). That fix introduced a new preamble section ID and a new preserve action, but the SDKs didn't expose either, so clients couldn't target just the identity preamble or opt a section out of a group-level remove.

What

This brings all six SDKs in line with the new runtime model:

  • New preamble section — targets just the identity preamble without touching its sibling sub-sections. The identity and tool_instructions IDs are now documented as section groups.
  • New preserve action — a no-op that protects an individually-addressable section (e.g. tone) from a group-level remove on its parent group.

Changes are applied consistently across the type/constant definitions for Node, Go, Python, .NET, and Java. Rust uses free-form section/action strings, so only its doc comments needed updating. Docs in getting-started.md and the Node/Go/.NET READMEs are updated to describe the groups and the fifth action.

Tests

Added an end-to-end should_use_replaced_preamble_section_in_response test to all six SDKs, backed by a shared replay snapshot under test/snapshots/. The test replaces the preamble section with a custom persona and asserts the persona surfaces in the assistant's reply, validating the customization flows through the full SDK -> RPC -> CLI stack.

A couple of notes for reviewers:

  • The snapshot was recorded against the real Copilot API (not hand-authored), then verified to replay cleanly. The replay proxy normalizes the system prompt to a ${system} placeholder, so the test asserts on observable assistant output rather than raw prompt bytes.
  • The Java test that asserts the exact count of section constants was bumped from 11 to 12 to account for PREAMBLE.
  • A preserve-specific E2E test was intentionally omitted: its effect lives entirely in the system-prompt bytes that the harness normalizes away, so it would carry no real signal. The constant additions are the meaningful SDK surface here.

Verified: Node/Go/Python E2E pass on replay; .NET/Java/Rust compile and format clean.

@MackinnonBuck MackinnonBuck requested a review from a team as a code owner June 17, 2026 23:12
Copilot AI review requested due to automatic review settings June 17, 2026 23:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SDK surface area for system-prompt customization to match the runtime’s newer model by adding a dedicated preamble section ID and a preserve section override action, then validating the new section via cross-SDK E2E coverage and documentation updates.

Changes:

  • Added preamble as a first-class system message section identifier, and clarified identity / tool_instructions as section groups in constants/docs across SDKs.
  • Added the preserve override action (no-op marker used to protect a leaf section from a group-level remove) in language SDK types/enums/docs (Rust docs only, since Rust uses free-form strings).
  • Added a new E2E scenario (should_use_replaced_preamble_section_in_response) and shared replay snapshot to verify preamble replacement flows through SDK → RPC → CLI.
Show a summary per file
File Description
test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml New shared replay snapshot for the preamble-replacement persona test.
rust/tests/e2e/system_message_sections.rs Adds Rust E2E test covering preamble replacement behavior.
rust/src/types.rs Updates SectionOverride doc comments to include the new preserve action.
python/e2e/test_system_message_sections_e2e.py Adds Python E2E test covering preamble replacement behavior.
python/copilot/session.py Extends Python system-message section/action types and metadata (preamble, preserve), updates section descriptions.
nodejs/test/e2e/system_message_sections.e2e.test.ts Adds Node E2E test covering preamble replacement behavior.
nodejs/src/types.ts Extends Node system-message section/action types and metadata (preamble, preserve), updates section descriptions.
nodejs/README.md Documents preamble, section groups, and the 5th action (preserve).
java/src/test/java/com/github/copilot/SystemMessageSectionsIT.java Adds Java E2E/integration test for preamble; updates constant-count assertions.
java/src/main/java/com/github/copilot/rpc/SystemMessageSections.java Adds PREAMBLE constant and clarifies IDENTITY as a group.
java/src/main/java/com/github/copilot/rpc/SectionOverrideAction.java Adds PRESERVE enum value with Javadoc describing semantics.
go/types.go Adds SectionPreamble and SectionActionPreserve, updates SectionIdentity docs to describe group semantics.
go/README.md Documents SectionPreamble, section groups, and the 5th action (preserve).
go/internal/e2e/system_message_sections_e2e_test.go Adds Go E2E test covering preamble replacement behavior.
dotnet/test/E2E/SystemMessageSectionsE2ETests.cs Adds .NET E2E test covering preamble replacement behavior.
dotnet/src/Types.cs Adds Preamble section identifier and Preserve override action.
dotnet/README.md Documents Preamble, section groups, and the 5th action (Preserve).
docs/getting-started.md Documents preamble, section groups, and the 5th action (preserve).

Copilot's findings

  • Files reviewed: 18/18 changed files
  • Comments generated: 1

Comment thread docs/getting-started.md Outdated
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.4M

Comments that could not be inline-anchored

go/README.md:168

This inline parameter-description list was not updated alongside the "Available section constants" paragraph below. SectionPreamble is missing from the keys: list, and the description of SectionIdentity should note it is a section group.

Suggested update:

  - **customize**: Selectively override individual sections via `Sections` map (keys: `SectionPreamble`, `SectionIdentity` (group), `SectionTone`, `SectionToolEfficiency`, `SectionEnvironmentContext`, `SectionCodeChangeRules`, `Sec…

</details>

@MackinnonBuck

Copy link
Copy Markdown
Collaborator Author

Thanks, good catch. Fixed in 077a390: added SectionPreamble to the front of the inline keys: list in the SystemMessage parameter-reference table (go/README.md line 168) so it matches the dedicated "Available section constants" paragraph and the other SDKs.

I left the group annotation out of that terse one-liner intentionally; the group semantics for SectionIdentity/SectionToolInstructions are already covered in the prose right below the constants list. Verified no other README has an analogous stale inline list.

@github-actions

This comment has been minimized.

MackinnonBuck and others added 5 commits June 24, 2026 13:31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a 'should_use_replaced_preamble_section_in_response' E2E test to all
six SDKs (Node, Go, Python, .NET, Java, Rust) exercising the new 'preamble'
section ID end-to-end, with a shared replay snapshot. Updates the Java
SystemMessageSections constant-count assertion from 11 to 12.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the unsupported 'a warning is emitted' claim from the system
message customization section so it matches the silent-fallback behavior
documented in the language READMEs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The new preamble test docstring exceeded the 100-char limit, failing
'ruff check' in the Python SDK Tests CI job across all platforms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The SystemMessage parameter-reference table's inline section-constant
list still started at SectionIdentity. Add SectionPreamble so it matches
the dedicated 'Available section constants' list and the other SDKs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SteveSandersonMS SteveSandersonMS force-pushed the mackinnonbuck/preamble-prompt-section branch from 077a390 to 11ad399 Compare June 24, 2026 12:31
@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

This PR maintains excellent consistency across all six SDK implementations. Here's what I verified:

New preamble section — all 6 SDKs ✅

SDK Addition
Node.js "preamble" added to SystemMessageSection union type + SYSTEM_MESSAGE_SECTIONS record
Python "preamble" added to SystemMessageSection Literal type + SYSTEM_MESSAGE_SECTIONS dict
Go SectionPreamble = "preamble" constant added
.NET SystemMessageSection.Preamble static property added
Java SystemMessageSections.PREAMBLE = "preamble" constant added (inherited by SystemPromptSections)
Rust Doc comments updated (by design — Rust uses free-form strings)

New preserve action — all 6 SDKs ✅

SDK Addition
Node.js "preserve" added to SectionOverrideAction union type
Python "preserve" added to SectionOverrideAction Literal union
Go SectionActionPreserve = "preserve" constant added
.NET SectionOverrideAction.Preserve enum member added
Java SectionOverrideAction.PRESERVE("preserve") enum member added
Rust Doc comments updated (free-form string; consistent with Rust's existing approach)

Ordering consistency ✅

The preserve action is inserted after prepend and before transform/callback in every SDK — consistent placement across all typed definitions.

The preamble section is placed before identity in every SDK — consistent placement.

E2E tests — all 6 SDKs ✅

Each SDK adds a should_use_replaced_preamble_section_in_response test exercising the same scenario (replacing preamble with a gardening persona, asserting the persona surfaces in the response), all backed by the shared snapshot at test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml.

Documentation ✅

  • docs/getting-started.md, nodejs/README.md, go/README.md, and dotnet/README.md all updated with preamble section, group concept, and preserve action.
  • Python, Java, and Rust READMEs don't contain the detailed section listing, so they correctly don't require updates.

No inconsistencies found

This PR is a well-executed cross-SDK change with high parity. No gaps identified.

Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.5M ·

@SteveSandersonMS SteveSandersonMS added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit 59168f0 Jun 24, 2026
40 checks passed
@SteveSandersonMS SteveSandersonMS deleted the mackinnonbuck/preamble-prompt-section branch June 24, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants